package com.ls.rbac.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ls.rbac.entity.Dept;
import com.ls.rbac.entity.User;
import com.ls.rbac.mapper.DeptMapper;
import com.ls.rbac.mapper.UserMapper;
import com.ls.rbac.service.IDeptService;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {


    @Resource
    private UserMapper userMapper;

    @Override
    public List<Dept> getDeptTreeAll() {
        List<Dept> allDept = this.list();
        Map<Integer, List<Dept>> deptMap = allDept.stream()
                .collect(Collectors.groupingBy(dept ->
                        dept.getPid() == null ? 0 : dept.getPid()));
        return buildDeptTree(deptMap, 0);
    }

    @Override
    public List<Dept> getDeptTreeParent(List<Dept> deptList) {
        Map<Integer, List<Dept>> deptMap = deptList.stream()
                .collect(Collectors.groupingBy(dept ->
                        dept.getPid() == null ? 0 : dept.getPid()));
        return buildDeptTree(deptMap, 0);
    }

    /**
     * 递归构建部门树
     */
    private List<Dept> buildDeptTree(Map<Integer, List<Dept>> deptMap, Integer pid) {
        List<Dept> deptTree = new ArrayList<>();
        List<Dept> deptList = deptMap.get(pid);
        if (deptList != null) {
            for (Dept dept : deptList) {
                List<Dept> children = buildDeptTree(deptMap, dept.getId());
                dept.setChildren(children);
                deptTree.add(dept);
            }
        }
        return deptTree;
    }

    @Override
    public List<Dept> listByPid(Integer pid) {
        LambdaQueryWrapper<Dept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dept::getPid, pid);
        queryWrapper.orderByAsc(Dept::getOrderNum); // 按排序号升序
        return this.list(queryWrapper);
    }


    @Override
    public List<Integer> getDeptAndChildrenIds(Integer deptId) {
        List<Integer> deptIds = new ArrayList<>();
        deptIds.add(deptId);
        List<Dept> allDeptList = this.list();
        if (allDeptList == null || allDeptList.isEmpty()) {
            return deptIds;
        }
        collectChildDeptIds(allDeptList, deptId, deptIds);
        return deptIds;
    }

    /**
     * 递归获取所有子部门ID
     */
    private void collectChildDeptIds(List<Dept> allDeptList, Integer deptId, List<Integer> deptIds) {
        allDeptList.stream()
                .filter(dept -> deptId.equals(dept.getPid()))
                .forEach(dept -> {
                    deptIds.add(dept.getId());
                    collectChildDeptIds(allDeptList, dept.getId(), deptIds);
                });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveDept(Dept dept) {
        if (dept.getPid() != null && dept.getPid() > 0) {
            Dept parentDept = this.getById(dept.getPid());
            if (parentDept != null) {
                dept.setParentName(parentDept.getDeptName());
            }
        } else {
            dept.setPid(0);
            dept.setParentName("无");
        }
        return this.save(dept);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDeptById(Dept dept) {
        // 处理上级部门名称
        if (dept.getPid() != null && dept.getPid() > 0) {
            // 检查循环引用
            if (dept.getId().equals(dept.getPid())) {
                throw new RuntimeException("上级部门不能选择自己");
            }
            // 不能选择自己的子部门作为父部门
            List<Integer> childDeptIds = this.getDeptAndChildrenIds(dept.getId());
            childDeptIds.remove(dept.getId());
            if (childDeptIds.contains(dept.getPid())) {
                throw new RuntimeException("上级部门不能选择当前部门的子部门");
            }
            Dept parentDept = this.getById(dept.getPid());
            if (parentDept != null) {
                dept.setParentName(parentDept.getDeptName());
            }
        } else {
            // 顶级部门
            dept.setPid(0);
            dept.setParentName("无");
        }
        return this.updateById(dept);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeDeptById(Integer id) {
        List<Dept> children = this.listByPid(id);
        if (!children.isEmpty()) {
            throw new RuntimeException("该部门下存在子部门，无法删除");
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getDeptId, id);
        List<User> users = userMapper.selectList(queryWrapper);
        if (!users.isEmpty()) {
            throw new RuntimeException("该部门下存在用户，无法删除");
        }
        return this.removeById(id);
    }
}